<template>
  <view
    class="app-tabs"
    :style="{ display: tabsDisplay }"
  >
    <view
      class="app-tabs__container"
      id="appTabs"
    >
      <view
        class="app-tabs__panel"
        :class="index === tabs.length - 1 ? 'm-r-0' : ''"
        v-for="(tab, index) in tabs"
        :key="tab[prop!.value]"
        @click="handleChangeTab(tab[prop!.value])"
      >
        <text :id="cacheTabId(tab[prop!.value])">{{ tab[prop!.label] }}</text>
      </view>
      <view
        id="tabsLine"
        class="app-tabs__underline"
        ref="tabsLine"
      />
    </view>
  </view>
</template>

<script setup lang="ts">
import type { TabProp } from './types'

interface Props {
  tabs: Record<string, any>[]
  current?: string
  prop?: TabProp
}
const props = withDefaults(defineProps<Props>(), {
  prop: () => {
    return {
      label: 'label',
      value: 'value'
    }
  }
})

const $emit = defineEmits(['change', 'update:current'])

const tabsDisplay = ref<'block' | 'none'>('block')

const currentTab = ref<string>('')
const handleChangeTab = (id: string) => {
  if (currentTab.value === id) return
  currentTab.value = id
  $emit('change', currentTab.value)
  $emit('update:current', currentTab.value)
}

const tabListMap = new Map()
const cacheTabId = (key: string): string => {
  const id = `tab-${key}`
  tabListMap.set(key, id)
  return id
}

let offsetLeft = 0
const setTabsOffsetLeft = () => {
  useSelectElement('#appTabs', result => {
    if (!Array.isArray(result) && result) {
      offsetLeft = result.left as number
    }
  })
}

const tabsLine = ref<AnyObject>()
const changeTabPosition = (id: string) => {
  useSelectElement(`#${tabListMap.get(id)}`, result => {
    if (!Array.isArray(result) && result) {
      tabsLine.value!.$el.style.width = `${result.width}px`
      tabsLine.value!.$el.style.left = `${
        (result.left as number) - offsetLeft
      }px`
    }
  })
}
const onWindowResizeListener = () => changeTabPosition(currentTab.value)
onMounted(() => {
  if (!props.tabs) {
    tabsDisplay.value = 'none'
    return
  }
  tabsDisplay.value = 'block'
  currentTab.value = props.current ?? props.tabs[0][props.prop.value]
  setTabsOffsetLeft()
  uni.onWindowResize(onWindowResizeListener)
})
onBeforeUnmount(() => uni.offWindowResize(onWindowResizeListener))

watch(currentTab, nv => {
  setTabsOffsetLeft()
  changeTabPosition(nv)
})
watch(
  () => props.current,
  nv => (currentTab.value = nv as string)
)
watch(
  () => props.tabs,
  () => {
    const { current } = props
    changeTabPosition(current ?? currentTab.value)
  },
  { deep: true }
)
</script>

<style lang="scss" scoped>
.app-tabs {
  z-index: 99;
  overflow-x: auto;
  .app-tabs__container {
    padding-bottom: 24rpx;
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    position: relative;
    box-sizing: border-box;
    .app-tabs__panel {
      flex: auto;
      // max-width: 130rpx;
      margin-right: 24rpx;
      display: flex;
      justify-content: center;
      font-size: 30rpx;
      // font-weight: bolder;
      color: #1f1f39;
      cursor: pointer;
      text {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
    }

    .app-tabs__underline {
      height: 8rpx;
      position: absolute;
      bottom: 0;
      z-index: 1;
      background-color: lightblue;
      border-radius: 50rpx;
      transition: all 0.3s ease;
    }
  }
}
.m-r-0 {
  margin-right: 0 !important;
}
</style>
